<?php
namespace gnomephp\mvc;

use \gnomephp\mvc\AuraRouter;
class Dispatcher{
	/**
	 *
	 * Keeps the microtime of when dispatch() was initialized.
	 * @var float
	 */
	static protected $startTime = 0;

	
	
	static public $map = null;
	
	static public $activeRoute = null;
	
	
	/**
	 * Gets the amount of time since Router::route() was called.
	 */
	static public function getRuntime(){
		return microtime(true) - self::$startTime;
	}

	
	/**
	 * Gets the current URL.
	 */
	static protected function getUrl(){
		$len = strlen($_SERVER['SCRIPT_NAME']);

		$out =  substr($_SERVER['PHP_SELF'], $len, strlen($_SERVER['PHP_SELF']));
		if (!$out)$out = '/';


		

		return $out;
	}	

	static public function dispatch(){

		session_start();
		
		
		self::$map = new AuraRouter\Map(new AuraRouter\RouteFactory);

		
		$map = &self::$map;
		
		include GNOME_APP_PATH.DIRECTORY_SEPARATOR.'config'. DIRECTORY_SEPARATOR . 'routes.php';

		// get the incoming request URI path
		$path = self::getUrl();


		
		// get the route based on the path and server
		$route = $map->match($path, $_SERVER);

		if (! $route) {
			// no route object was returned
			throw new RouterException("404 - No application route was found for that URI path.");
		}

		// does the route indicate a controller?
		if (isset($route->values['controller'])) {
			// take the controller class directly from the route
			$controller = $route->values['controller'];
		} else {
			throw new RouterException("404 - Route does not indicate a controller.");
		}

		// does the route indicate an action?
		if (isset($route->values['action'])) {
			// take the action method directly from the route
			$action = $route->values['action'];
		} else {
			// use a default action
			$action = 'index';
		}

		try{
			$fullNS = GNOME_APP_NS.'\controller\\'.$controller;
			// instantiate the controller class
			$page = new $fullNS();

			
			
			if (!method_exists($page, $action)){
				throw new RouterException("404 - No Route found for URL: ".self::getUrl().". Could not load Action.");
			}
			
			self::$activeRoute = $route->getName();
			
			// invoke the action method with the route values
			$args = $route->values;
			unset($args['controller']);
			unset($args['action']);
			
			$refObject = new \ReflectionObject($page);
			
			try{
				// Lets do a security check if it does implement the Secure interface. 
				if ($refObject->implementsInterface('gnomephp\security\Secure')){
					
					\gnomephp\doctrine\Doctrine::load();
					
					$ns = \gnomephp\security\Security::getSessionModelPath();
					$userSession = $ns::getValidSession($page->session->get(\gnomephp\security\Security::SECURITY_TOKEN), $ns);
					
					if (!$page->hasAccessTo($action, $userSession)){
						throw new \gnomephp\security\AccessException();
					}
				}
			}catch(\gnomephp\security\AccessException $e){
				$page->redirect($page->view->url->linkTo('security_login'));
			}
			
			unset($refObject);
			call_user_func_array(array($page, $action), array_values($args));
		
			// Delete data that should not be here anymore.
			// This is one time data that should be deleted.
			$session = new \gnomephp\Session();
			$session->delete('gnomephp.messages');
			$session->save();
			
			
		}catch(\gnomephp\AutoLoaderException $e){
			throw new RouterException("404 - No Route found for URL: ".self::getUrl().". Could not load Controller." . $e->getMessage());
		}
		
	}

}